﻿// Copyright (c) Vitaly Kamiansky. All rights reserved. 
// See License.txt in the project root.

using System;
using System.ComponentModel;

namespace Property.Objects
{
    public abstract class Property<T> : IOutput<T>, IDisposable, INotifyPropertyChanged, INotifyPropertyChanging
    {
        protected Property(T defaultValue)
        {
            ValueState = defaultValue;
        }

        private T ValueState;
        public virtual T Value
        {
            get
            {
                return ValueState;
            }
            private set
            {
                OnPropertyChanging("Value");
                ValueState = value;
                OnPropertyChanged("Value");
            }
        }

        public virtual T DebugValue
        {
            get
            {
                return ValueState;
            }
        }

        private bool IsLoadingState;
        public virtual bool IsLoading
        {
            get
            {
                return IsLoadingState;
            }
            private set
            {
                OnPropertyChanging("IsLoading");
                IsLoadingState = value;
                OnPropertyChanged("IsLoading");
            }
        }

        protected virtual void ApplyValue(T value)
        {
            Value = value;
        }

        protected virtual void ApplyStatus(bool status)
        {
            IsLoading = status;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangingEventHandler PropertyChanging;

        protected void OnPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }

        public abstract void Dispose();
    }
}
